package org.top10.parser;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.top10.collector.Collector;
import org.top10.collector.Filter;
import org.top10.entity.CollectEntity;
import org.top10.executor.ParseSource;
import org.top10.util.NdcFunction;
import org.top10.util.TOP10Global;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public abstract class TOPParserImpl implements TOPParser {
	
	public TOPParserImpl(String c, int t, String u) {
		this.cpation = c;
		this.type=t;
		this.url = u;
	}

	// 所有解析器的公有方法或公有属性放在这里
	protected String cpation; // 标题，你采集的这个东西的标题
	protected int type; // 分类,比如电影，新闻等
	protected String url; // 采集的URL
	protected String encoding; 
	private final static int TryCount = 3;// 尝试次数
	private final static long SLEEP_TIME = 1000 * 60 * 10; // 10,20
	
	/*
	 * getParseText()方法实现处理发请求取文本，解析文本，解析文本的只要由它调用parse实现
	 * 
	 */
	
	public List<CollectEntity> dealText(String encoding)throws Exception{
		ParseSource doc = null;
		int count = 0;
		long sleep = SLEEP_TIME;
		try {
			while (count++ < TryCount) {
				doc = Collector.collectDoc(url,encoding, true);
				if (doc != null)
					break;
				if (count != TryCount) {
					Thread.sleep(sleep);
					sleep *= count;
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return parse(doc);
	}

	public abstract List<CollectEntity> parse(ParseSource doc)throws Exception;
	
	/**
	 * 找到与该模式匹配的节点
	 */
	protected  Node getNodeByPattern(Node root, String tagName,
			Pattern p) {

		if (root.getNodeType() == Node.ELEMENT_NODE) {//判断是否为元素节点
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))//判断是否为样式或js
				return null;
			
			if (elmt.getNodeName().equalsIgnoreCase(tagName)
					&&(p==null|| p.matcher(elmt.getTextContent()).find())) {
				return root;
			}
		
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node t = getNodeByPattern(children.item(i), tagName, p);
				if (t!=null)return t;
			}
		}
		return null;
	}
	protected Node getChildByName(Node parent,String name){
		NodeList childrens = parent.getChildNodes();
		for (int i = 0; i < childrens.getLength(); i++) {
			Node c=childrens.item(i);
			if(c.getNodeType() != Node.ELEMENT_NODE)continue;
			if(c.getNodeName().equalsIgnoreCase(name)){
				return c;
			}
		}
		return null;
	}
	protected  Node getNodeByText(Node root, String tagName,String text) {
		if (root.getNodeType() == Node.ELEMENT_NODE) {//判断是否为元素节点
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))//判断是否为样式或js
				return null;
//			System.out.println(elmt.getNodeName());
//			if(elmt.getNodeName().equalsIgnoreCase(tagName)){
//				System.out.println(elmt.getTextContent());
//			}
			//System.out.println(getNodeByAttr("a","class","f12blackB",root));
			if (elmt.getNodeName().equalsIgnoreCase(tagName)&&elmt.getTextContent()!=null&&text.equals(elmt.getTextContent().trim())) {
				return root;
			}
		
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node t = getNodeByText(children.item(i), tagName, text);
				if (t!=null)return t;
			}
		}
		return null;
	}
	protected  Node getNodeContentText(Node root, String tagName,String text) {
		if (root.getNodeType() == Node.ELEMENT_NODE) {//判断是否为元素节点
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))//判断是否为样式或js
				return null;
			
			if (elmt.getNodeName().equalsIgnoreCase(tagName)&&elmt.getTextContent()!=null&&elmt.getTextContent().indexOf(text)!=-1) {
				return root;
			}
		
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node t = getNodeContentText(children.item(i), tagName, text);
				if (t!=null)return t;
			}
		}
		return null;
	}
	protected  Node getNodeByFilter(Node root, String tagName,
			Filter filter) {

		if (root.getNodeType() == Node.ELEMENT_NODE) {//判断是否为元素节点
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))//判断是否为样式或js
				return null;
			
			if (elmt.getNodeName().equalsIgnoreCase(tagName)
					&&filter.pass(root)) {
				return root;
			}
		
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node t = getNodeByFilter(children.item(i), tagName,filter);
				if (t!=null)return t;
			}
		}
		return null;
	}
	protected Node getNodeByPattern(Node root, String tagName) {
			return getNodeByPattern(root,tagName ,null);
	}
	/**
	 * 将所有与tagName匹配的节点或子节点放入List里面，List内的排序按深度优先
	 * @param root
	 * @param tagName 
	 * @param tags
	 */
	protected  void getAllTagsByParent(Node root,String tagName,List<Node>tags){
		if(root==null)return ;
		if(NdcFunction.isEmptyStr(tagName)||tags==null)
			throw new IllegalArgumentException("tagName or node is null");
		if (root.getNodeType() == Node.ELEMENT_NODE) {
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))
				return ;
			if (tagName.equalsIgnoreCase(root.getNodeName())) {
				tags.add(root);
			}
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				getAllTagsByParent(children.item(i),tagName,tags);
			}
		}
	}
	protected  void getAllTagsByParent(Node root,String tagName,List<Node>tags,Filter f){
		if(root==null)return ;
		if(NdcFunction.isEmptyStr(tagName)||tags==null)
			throw new IllegalArgumentException("tagName or node is null");
		if (root.getNodeType() == Node.ELEMENT_NODE) {
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))
				return ;
			if (tagName.equalsIgnoreCase(root.getNodeName())&&f.pass(root)) {
				tags.add(root);
			}
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				getAllTagsByParent(children.item(i),tagName,tags,f);
			}
		}
	}
	/**
	 * 获取节点指定属性的值
	 * @param node
	 * @param attr
	 * @return
	 */
	protected  String getAttrValueByTag(Node node,String attr) {
		if(node==null)return null;
		if(NdcFunction.isEmptyStr(attr))
			throw new IllegalArgumentException("attr is null");
		if (node.getNodeType() == Node.ELEMENT_NODE) {
				NamedNodeMap attrs = node.getAttributes();
				for (int i = 0; i < attrs.getLength(); i++) {
					if (attr.equalsIgnoreCase(attrs.item(i).getNodeName())) {
						return attrs.item(i).getNodeValue();// 在DOM树中，属性是一个结点。
					}
				}
		}
		return null;
	}
	/**
	 * 
	 * @param tagName
	 * @param attrName
	 * @param sign
	 * @param root
	 * @return
	 */
	public Node getNodeByAttr(String tagName,String attrName ,String sign, Node root) {
		if (root.getNodeType() == Node.ELEMENT_NODE) {
			Element elmt = (Element) root;
			if (elmt.getTagName().equals("STYLE")
					|| elmt.getTagName().equals("SCRIPT"))
				return null;
			if (elmt.getNodeName().equalsIgnoreCase(tagName)) {
				String value = getAttrValueByTag(root, attrName);
				
				if (value!=null&&value.endsWith(sign))
					return root;
			}
			NodeList children = elmt.getChildNodes();
			for (int i = 0; i < children.getLength(); i++) {
				Node t = getNodeByAttr(tagName,attrName,sign,children.item(i));
				if (t != null)
					return t;
			}
		}
		return null;
	}
	public String getCpation() {
		return cpation;
	}

	public void setCpation(String cpation) {
		this.cpation = cpation;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}
	/**
	 * 解析数组类型的json数据,必需以“[”开头
	 */
	protected  List turnJson2List(String json,Class<?> type){
		JSONArray jsonArray = JSONArray.fromObject(json);
		List list=new ArrayList();
		for (int i = 0; i < jsonArray.size()&& i<10 ; i++) {
			   Object o = jsonArray.get(i);
			   JSONObject jsonObject = JSONObject.fromObject(o);
			   list.add(JSONObject.toBean(jsonObject,type));
			}
		return list;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
}
